package com.demo.function.shiro.config;

import com.demo.function.shiro.jwt.JWTFilter;
import jakarta.servlet.Filter;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    /**
     * 创建安全管理器
     * 用于 web 环境的实现，底层其实使用ServletContainerSessionManager，直接使用 Servlet 容器的会话。
     * session失效，用户当前shiro权限也失效。需要重新获取权限数据。
     * 同时DefaultWebSecurityManager也是管理session相关的超时时间，失效时间等相关配置
     */
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);
        return securityManager;
    }

    /**
     * ShiroFilter过滤所有请求
     */
    @Bean(name = "shiroFilterFactoryBean")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //给ShiroFilter配置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        //jwt token过滤
        Map<String, Filter> filters = new HashMap<>();
        filters.put("jwt", new JWTFilter());
        shiroFilterFactoryBean.setFilters(filters);

        //配置系统受限资源 和 配置系统公共资源
        Map<String, String> map = new LinkedHashMap<>();
        // value=anon表示这个资源不需要认证和授权
        map.put("/shiro/getMsg","anon");
        map.put("/shiro/login","anon");
        map.put("/shiro/logout","anon");
        // value=jwt表示这个资源需要认证和授权，需要走上面定义的jwt filter
        map.put("/shiro/*","jwt");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);

        return shiroFilterFactoryBean;
    }

    @Bean("lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
}
